package com.longe.netty.transferFiles.client;

import com.longe.netty.transferFiles.domain.FileTransferProtocol;
import com.longe.netty.transferFiles.domain.TransferConstants;
import com.longe.netty.transferFiles.domain.TransferData;
import com.longe.netty.transferFiles.domain.TransferInstruct;
import com.longe.netty.transferFiles.util.FileUtil;
import com.longe.netty.transferFiles.util.MsgUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;

public class MyClientHandler extends ChannelInboundHandlerAdapter {

    /**
     * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        SocketChannel channel = (SocketChannel) ctx.channel();
        System.err.println("成功连接服务端,其IP:" + channel.localAddress().getHostString());
    }

    /**
     * 当客户端主动断开服务端的链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.err.println("断开链接" + ctx.channel().localAddress().toString());
        super.channelInactive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //数据格式验证
        if (!(msg instanceof FileTransferProtocol)) return;

        FileTransferProtocol fileTransferProtocol = (FileTransferProtocol) msg;
        //0传输文件'请求'、1文件传输'指令'、2文件传输'数据'
        switch (fileTransferProtocol.getTransferType()) {
            case 1:
                TransferInstruct transferInstruct = (TransferInstruct) fileTransferProtocol.getTransferObj();
                if (TransferConstants.FileStatus.COMPLETE == transferInstruct.getFileTransferStatus()) {
                    return;
                }
                //特别说明,这个if中的代码纯粹是为了验证断点续传的
                //当文件传输一部分的时候,代码执行到这里客户端会推出。当我们再次启动客户端的时候,看是否接着之前的续传
                //这里会有一定的概率,多试几次就能出现断点续传的情况
                /*if (TransferConstants.FileStatus.CENTER == transferInstruct.getFileTransferStatus() &&
                new Random().nextBoolean() == true) {
                    ctx.flush();
                    ctx.close();
                    System.exit(-1);
                    return;
                }*/

                TransferData transferData = FileUtil
                        .readFile(transferInstruct.getFileUrl(), transferInstruct.getReadPosition());
                ctx.writeAndFlush(MsgUtil.buildTransferData(transferData));

                int bytes = transferData.getEndPosition() - transferData.getBeginPosition();
                System.err.println("客户端传输文件信息。 FILE：" + transferData.getFileName() + " SIZE(byte)：" + bytes);
                break;
            default:
                break;
        }
    }

    /**
     * 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        System.err.println("异常信息：\r\n" + cause.getMessage());
    }

}